/**
 * @file bull_hal_sys_queue.c
 * @brief 
 * @author yejing (yejh@gongniu.cn)
 * @version 1.0
 * @date 2024-05-09
 * 
 * Copyright 2021-2023 GongNiu Inc. All Rights Reserved.
 * 
 */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#include "bull_hal_adapter.h"
#include "bull_hal_sys_system.h"
#include "bull_hal_sys_memory.h"
#include "bull_hal_sys_mutex.h"


#define portYIELD_FROM_ISR_ex( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()

/***********************************************************
*************************micro define***********************
***********************************************************/
typedef struct {
    xQueueHandle queue;
} QUEUE_MANAGE, *P_QUEUE_MANAGE;


/***********************************************************
*************************variable define********************
***********************************************************/



/***********************************************************
*************************function define********************
***********************************************************/


/**
 * @brief create queue
 *
 * @param[out]     queue      queue to be create
 * @param[in]      size       the deep of the queue
 * @return  OPRT_OS_ADAPTER_OK: SUCCESS other:fail
 */
int bull_hal_sys_queue_create(QUEUE_HANDLE *queue, int message_size, int number_of_messages)
{
    P_QUEUE_MANAGE pQueueManage;

    if (NULL == queue) {
        return OPRT_OS_ADAPTER_INVALID_PARM;
    }

    *queue = NULL;

    pQueueManage = (P_QUEUE_MANAGE)bull_hal_sys_memory_malloc(sizeof(QUEUE_MANAGE));
    if (pQueueManage == NULL) {
        return OPRT_OS_ADAPTER_MALLOC_FAILED;
    }

    pQueueManage->queue = xQueueCreate(number_of_messages, message_size);

    if (pQueueManage->queue == NULL) {
        bull_hal_sys_memory_free(pQueueManage);
        return OPRT_OS_ADAPTER_QUEUE_CREAT_FAILED;
    } else {
        *queue = (QUEUE_HANDLE)pQueueManage;
    }

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief free queue
 *
 * @param[in]     queue      queue to be free
 * @return  void
 */
void bull_hal_sys_queue_delete(QUEUE_HANDLE queue)
{
    P_QUEUE_MANAGE pQueueManage;

    if (NULL == queue) {
        return;
    }

	pQueueManage = (P_QUEUE_MANAGE)queue;

    vQueueDelete(pQueueManage->queue);
    bull_hal_sys_memory_free(pQueueManage);
}

/**
 * @brief fetch msg from queue in timeout ms, copy data to queue
 *
 * @param[in]      queue      queue to post
 * @param[in]      msg        msg to post
 * @param[in]      timeout    max time to wait for msg(ms), BULL_HAL_SYS_QUEUE_FOREVER means forever wait
 * @return  int OPRT_OS_ADAPTER_OK:success    other:fail
 */
int bull_hal_sys_queue_post(QUEUE_HANDLE queue, void *msg, unsigned int timeout)
{
    int ret = pdPASS;
    P_QUEUE_MANAGE pQueueManage;
	signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    
    if (NULL == queue) {
        return OPRT_OS_ADAPTER_INVALID_PARM;
    }

	pQueueManage = (P_QUEUE_MANAGE)queue;
    
    if(FALSE == bull_hal_sys_is_in_isr()) {
        ret = xQueueSend( pQueueManage->queue, msg, (timeout == BULL_HAL_SYS_QUEUE_FOREVER) ? portMAX_DELAY : (timeout/ bull_hal_sys_get_tickratems()));
    } else {
        ret = xQueueSendFromISR( pQueueManage->queue, msg, &xHigherPriorityTaskWoken);
        // portYIELD_FROM_ISR_ex(xHigherPriorityTaskWoken);
    }
    
	return ((pdPASS == ret) ? OPRT_OS_ADAPTER_OK : OPRT_OS_ADAPTER_QUEUE_SEND_FAIL);
}

/**
 * @brief fetch msg from queue in timeout ms, copy data from queue
 *
 * @param[in]      queue      queue to post
 * @param[out]     msg        msg to fetch
 * @param[in]      timeout    max time to wait for msg(ms), BULL_HAL_SYS_QUEUE_FOREVER means forever wait
 * @return  int OPRT_OS_ADAPTER_OK:success    other:fail
 */
int bull_hal_sys_queue_fetch(QUEUE_HANDLE queue, void *msg, unsigned int timeout)
{
	int ret = pdTRUE;
    P_QUEUE_MANAGE pQueueManage;
    
    if (NULL == queue) {
        return OPRT_OS_ADAPTER_INVALID_PARM;
    }
	
	pQueueManage = (P_QUEUE_MANAGE)queue;

    ret = xQueueReceive(pQueueManage->queue, msg, (timeout == BULL_HAL_SYS_QUEUE_FOREVER) ? portMAX_DELAY : (timeout / bull_hal_sys_get_tickratems()));

	return ((pdTRUE == ret) ? OPRT_OS_ADAPTER_OK : OPRT_OS_ADAPTER_QUEUE_RECV_FAIL);
}



